/*
 * 
 */

/**
 *
 * @author Lorena Vazquez
 */
import EventPackage.*;
import java.util.*;
import java.io.*;

public class MaintenanceMonitor extends Thread {

    private EventManagerInterface em = null;// Interface object to the event manager
    private String EvtMgrIP = null;	//IP Address of the Event Manager
    boolean Registered = true;		// Signifies that this class is registered with an event manager.
    HashMap<Integer, Device> installedDevices = null;//list of
    boolean StateChanged = false;   //Signifies if state of any device changed
    int waitTime = 2500;
    int heartBeatThreshold = 2500;
    String installedFilename = "InstalledDevices.txt";

    public MaintenanceMonitor() {

        // event manager is on the local system
        try {
            // Here we create an event manager interface object. This assumes
            // that the event manager is on the local machine

            em = new EventManagerInterface();
            getInstalledDevices();


        } catch (Exception e) {
            System.out.println("MaintenanceConsole::Error instantiating event manager interface: " + e);
            Registered = false;

        } // catch
    }

    public MaintenanceMonitor(String EvtMgrIP) {
        // event manager is on remote system
        this.EvtMgrIP = EvtMgrIP;
        try {
            // Here we create an event manager interface object.

            em = new EventManagerInterface(this.EvtMgrIP);
     

        } catch (Exception e) {
            System.out.println("MaintenanceConsole::Error instantiating event manager interface: " + e);
            Registered = false;

        } // catch
    }

    public MaintenanceMonitor(String EvtMgrIP, String FileName) {
        this.installedFilename = FileName;
        this.EvtMgrIP = EvtMgrIP;
        if (EvtMgrIP == null) {
            // event manager is on the local system
            try {
                // Here we create an event manager interface object. This assumes
                // that the event manager is on the local machine

                em = new EventManagerInterface();
         


            } catch (Exception e) {
                System.out.println("MaintenanceConsole::Error instantiating event manager interface: " + e);
                Registered = false;

            } // catch
        } else {
            try {
                // Here we create an event manager interface object.

                em = new EventManagerInterface(this.EvtMgrIP);
               

            } catch (Exception e) {
                System.out.println("MaintenanceConsole::Error instantiating event manager interface: " + e);
                Registered = false;
            }
        }
    }

    @Override
    public void run() {
        Event Evt = null;				// Event object
        EventQueue eq = null;			// Message Queue       
        boolean Done = false;
       
        if (em != null) {
            //Connected to Event manager. We can process events now
            System.out.println("Connected to Event Manager");
            getInstalledDevices();
            try {
                while (!Done) {
                    // Here we get our event queue from the event manager

                    try {
                        eq = em.GetEventQueue();
                        int qlen = eq.GetSize();
                        Integer ElementID;
                        for (int i = 0; i < qlen; i++) {
                            Evt = eq.GetEvent();

                            if (Evt.GetEventId() == 100) //Hearbeat event
                            {
                                //System.out.println("Hearbeat Received " +Evt.GetMessage() );
                                Date today = new Date();
                                try {
                                    //Get device ID from hearbeat event
                                    ElementID = Integer.parseInt(Evt.GetMessage());
                                    Device device = null;
                                    //if device is is in cache update last hearbeat time
                                    if (installedDevices.containsKey(ElementID)) {
                                        device = installedDevices.get(ElementID);
                                        if (device.getStatus().matches("Inactive")) {
                                            device.setStatus("Active");
                                            StateChanged = true;
                                        }
                                         
                                        device.setLastHeartBeat(today.getTime());
                                        installedDevices.put(ElementID, device);
                                    } else {
                                        device = new Device();
                                        device.setId(ElementID);
                                        device.setDescription("UNKNOWN");
                                        device.setStatus("Active");
                                        device.setLastHeartBeat(today.getTime());
                                        installedDevices.put(ElementID, device);
                                        StateChanged = true;
                                    }

                                    //else add device and StateChanged to true
                                    // StateChanged


                                } catch (Exception e) {
                                }
                            }
                            if (Evt.GetEventId() == 99) //End simulation
                            {
                                Done = true;

                                try {
                                    em.UnRegister();

                                } // try
                                catch (Exception e) {
                                    System.out.println("Error unregistering: " + e);

                                } // catch
                            }

                        }//for
                        //Check all the installedDevices and compare to last hearbeat received
                        //if last time HB received verus right now is greater than threshold, update status of device
                        // and update screen
                        Date dateNow = new Date();
                        long now = dateNow.getTime();
                        for (Map.Entry<Integer, Device> entry : installedDevices.entrySet()) {
                            Integer outDeviceId = entry.getKey();
                            Device outDeviceObj = entry.getValue();

                            if ((now - outDeviceObj.getLastHeartBeat()) > heartBeatThreshold) {
                                outDeviceObj.setStatus("Inactive");
                                StateChanged = true;
                            }


                        }
                        if (StateChanged) {

                            System.out.println("\n\nDevice ID \t\t Device Name \t\t Device Description \t\t Status ");
                            for (Map.Entry<Integer, Device> entry : installedDevices.entrySet()) {
                                Integer outDeviceId = entry.getKey();
                                Device outDeviceObj = entry.getValue();
                                System.out.println(outDeviceObj.getId() + "\t\t" + outDeviceObj.getName() + "\t\t" + outDeviceObj.getDescription() + "\t\t" + outDeviceObj.getStatus());
                            }
                            StateChanged = false;//reset state
                        }
                        Thread.sleep(waitTime);

                    } // try
                    catch (Exception e) {
                    }

                }
            } catch (Exception e) {
            }

        }

    }

    public boolean IsRegistered() {
        return (Registered);

    }

    private void getInstalledDevices() {
        System.out.println("Device ID \t\t Device Name \t\t Device Description \t\t Status ");
         Date today = new Date();
        try {
            installedDevices = new HashMap<Integer, Device>();
            BufferedReader input = new BufferedReader(new FileReader(installedFilename));

            String line;
            while ((line = input.readLine()) != null) {
                String[] row = line.split("\t");
                Device installedDevice = new Device();
                installedDevice.setId(Integer.parseInt(row[0]));
                installedDevice.setName(row[1]);
                installedDevice.setDescription(row[2]);
                installedDevice.setStatus("Inactive");
                installedDevice.setLastHeartBeat(today.getTime());
                installedDevices.put(installedDevice.getId(), installedDevice);
                System.out.println(installedDevice.getId() + "\t\t" + installedDevice.getName() + "\t\t" + installedDevice.getDescription() + "\t\t" + installedDevice.getStatus());
            }
            input.close();
        } catch (Exception e) {
            System.out.println("Error reading installed devices file" + e);
        }
    }
}
